package xyz.coderl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ZhongTaiExcel {
    /**
     * 总页数
     */
    private int totalPages;

    /**
     * 总行数
     */
    private int totalRows;

    /**
     * 首行开始
     */
    private int topRows;

    /**
     * 总列数
     */
    private int totalCells;

    private static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");

    /**
     * 全部从零开始
     */
    public ZhongTaiExcel(int totalPages, int topRows, int totalCells) {
        this.totalPages = totalPages;
        this.topRows = topRows;
        this.totalCells = totalCells + 1;
    }

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // 存放待读取行数
        LinkedHashMap<Integer, Integer> mapFromExcel = new LinkedHashMap<>();
        mapFromExcel.put(1, 24);
        mapFromExcel.put(26, 26);
        mapFromExcel.put(28, 30);
        mapFromExcel.put(32, 32);

        codeGenerationConvert(mapFromExcel, 0, 3, 16, "D:\\OneDrive - coderl98\\Desktop\\全国平台资料\\行业模型与履约平台映射关系(交强险-理赔)-0527.xlsx");
//        codeGenerationDto(mapFromExcel, 0, 3, 16, "D:\\OneDrive - coderl98\\Desktop\\全国平台资料\\行业模型与履约平台映射关系(交强险-理赔)-0527.xlsx");
//        codeGenerationValid(mapFromExcel, 0, 3, 16, "D:\\OneDrive - coderl98\\Desktop\\全国平台资料\\行业模型与履约平台映射关系(交强险-理赔)-0527.xlsx");
//        codeGenerationEncode(mapFromExcel, 0, 3, 16, "D:\\OneDrive - coderl98\\Desktop\\全国平台资料\\行业模型与履约平台映射关系(交强险-理赔)-0527.xlsx");
//        codeGenerationDecode(mapFromExcel, 0,  8, 16, "D:\\OneDrive - coderl98\\Desktop\\全国平台资料\\行业模型与履约平台映射关系(交强险-理赔)-0527.xlsx");
    }

    /**
     * 自动生成convert代码转换代码
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      请求数据起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void codeGenerationConvert(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        // 拼写override方法 循环第一行时加载此方法
        for (Map.Entry<Integer, Integer> entry : set) {
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);
                if (i == entry.getKey() - 1 && i == 0) {
                    // 拼接固定方法前部代码
                    System.out.println("     /**\n" +
                            "     * 入参map转换方法\n" +
                            "     *\n" +
                            "     * @param map 待解析map\n" +
                            "     * @return com.cic.businsurance.regulatory.clmci.domain.platformdo.PlatformClaimDto\n" +
                            "     * @throws Exception 异常上抛\n" +
                            "     * @author 李坤尧\n" +
                            "     * @date 2021/5/31 9:49\n" +
                            "     * @since JDK1.8\n" +
                            "     */" +
                            "    @Override\n" +
                            "    public PlatformClaimDto sendPlatfromDto(Map<String, Object> map) throws Exception {\n" +
                            "        PlatformClaimDto requestDto = new PlatformClaimDto();\n" +
                            "        // 调用对应子方法\n");
                    // 解析拼接子方法的方法名
                    String methodNames = innerList.get(11);
                    String[] methodNameArray = methodNames.split("\\.");
                    for (String methodName : methodNameArray) {
                        System.out.println("        " + toLowerCaseFirstOne(lineToHump(methodName)) + "Convert(map, requestDto);");
                    }
                    System.out.println("        return requestDto;\n" +
                            "    }");
                }
            }
        }

        // 拼写子方法的代码
        for (Map.Entry<Integer, Integer> entry : set) {
            // TODO System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());

            Map<String, String> listDtoMap = new HashMap<>();
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);
                if (i == entry.getKey() - 1) {
                    // 拼接固定方法前部代码 包括注释 方法名 入参反参 方法类型等
                    System.out.println("    /**\n" +
                            "     * " + innerList.get(4) + "解析\n" +
                            "     *\n" +
                            "     * @param map        待解析map\n" +
                            "     * @param requestDto 解析后对象\n" +
                            "     * @throws Exception 异常上抛\n" +
                            "     * @author 李坤尧\n" +
                            "     * @date 2021/5/27 16:14\n" +
                            "     * @since JDK1.8\n" +
                            "     */\n" +
                            "    private void " + toLowerCaseFirstOne(lineToHump(innerList.get(1))) + "Convert(Map<String, Object> map, PlatformClaimDto requestDto) throws Exception {");
                }
                if (!(StringUtils.isEmpty(innerList.get(7)) || StringUtils.isEmpty(innerList.get(6)))) {
                    listDtoMap.put(innerList.get(7), innerList.get(6));
                }
            }

            // 生成解析获取List对象代码
            for (String listDtoName : listDtoMap.keySet()) {
                if (listDtoName.endsWith("s")) {
                    // 取值时的key及中文名
                    String[] cnAndEnName = listDtoName.split("\\.");
                    // 接收时的Dto及中文名
                    String[] dtoCnAndEnName = listDtoMap.get(listDtoName).split("\\.");
                    System.out.println("        // " + cnAndEnName[0]);
                    System.out.println("        List<Map<String, Object>> " + toLowerCaseFirstOne(dtoCnAndEnName[1].replace("DTO", "")) + "List = (List<Map<String, Object>>) MapUtils.getValue(map, \"" + cnAndEnName[1] + "\");");
                }
            }
            System.out.println();

            // 生成获取单一对象代码 包括解析判断获取List内的单一对象
            for (String listDtoName : listDtoMap.keySet()) {
                if (listDtoName.endsWith("s")) {
                    // 取值时的key及中文名
                    String[] cnAndEnName = listDtoName.split("\\.");
                    // 接收时的Dto及中文名
                    String[] dtoCnAndEnName = listDtoMap.get(listDtoName).split("\\.");
                    System.out.println("        // " + cnAndEnName[0]);
                    System.out.println("        Map<String, Object> " + toLowerCaseFirstOne(dtoCnAndEnName[1].replace("DTO", "")) + "Map = MapUtils.stringObjectMap(" + toLowerCaseFirstOne(dtoCnAndEnName[1].replace("DTO", "")) + "List, \"\", \"\", \"\");");
                } else {
                    // 取值时的key及中文名
                    String[] cnAndEnName = listDtoName.split("\\.");
                    // 接收时的Dto及中文名
                    String[] dtoCnAndEnName = listDtoMap.get(listDtoName).split("\\.");
                    System.out.println("        // " + cnAndEnName[0]);
                    System.out.println("        Map<String, Object> " + toLowerCaseFirstOne(dtoCnAndEnName[1].replace("DTO", "")) + "Map = (Map<String, Object>) MapUtils.getValue(map, \"" + dtoCnAndEnName[1] + "\");");
                }
            }

            System.out.println();

            // 首先循环确认监管有哪几个对象
            Set<String> localDtoSet = new HashSet<>();
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                localDtoSet.add(innerList.get(10));
            }

            // 然后循环分别取出对像所在行
            ArrayList<ArrayList<ArrayList<String>>> allRowList = new ArrayList<>();
            for (String localDtoName : localDtoSet) {
                // 单个本地对象所在行集合
                ArrayList<ArrayList<String>> dtoList = new ArrayList<>();
                for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                    // 获取单行数据
                    ArrayList<String> innerList = dataList.get(i);
                    if (localDtoName.equals(innerList.get(10))) {
                        dtoList.add(innerList);
                    }
                }
                allRowList.add(dtoList);
            }

            // 最后循环生成set方法
            for (ArrayList<ArrayList<String>> dtoList : allRowList) {
                for (int i = 0; i < dtoList.size(); i++) {
                    ArrayList<String> innerList = dtoList.get(i);
                    if (i == 0) {
                        // 集合时创建List
                        if (innerList.get(10).endsWith("List")) {
                            System.out.println("        List<" + toUpperCaseFirstOne(innerList.get(10)).replace("List", "") + "> " + innerList.get(10) + " = new ArrayList<>();");
                            System.out.println("            Map<String, Object> entityMap : ) {");
                        }
                        // 创建本地存储对象
                        String dtoName = innerList.get(10).replace("List", "");
                        if (!"requestDto".equals(innerList.get(10))) {
                            System.out.println(toUpperCaseFirstOne("        "+toUpperCaseFirstOne(dtoName) + " " + toLowerCaseFirstOne(dtoName) + " = new " + toUpperCaseFirstOne(dtoName) + "();"));
                        }
                    }
                    if (!StringUtils.isEmpty(innerList.get(6))) {
                        // 接收时的Dto及中文名
                        String[] dtoCnAndEnName = innerList.get(6).split("\\.");
                        System.out.println("        // " + innerList.get(3) + "\n" +
                                "        " + innerList.get(10) + ".set" + toUpperCaseFirstOne(lineToHump(innerList.get(2))) + "(MapUtils.methodGetValue(" + toLowerCaseFirstOne(dtoCnAndEnName[1].replace("DTO", "")) + "Map, \"" + innerList.get(8) + "\", \"" + innerList.get(9) + "\"));");
                    }
                    if (i == dtoList.size() - 1) {
                        if (innerList.get(10).endsWith("List")) {
                            System.out.println("        }");
                        }
                    }
                }
                for (ArrayList<String> innerList : dtoList) {

                }
                System.out.println();
            }

            System.out.println("    }\n");
        }
    }

    /**
     * 自动生成encode请求报文拼接代码
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      请求数据起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void codeGenerationEncode(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        System.out.println("    @Autowired\n" +
                "    private PubTools pubTools;" +
                "@Override\n" +
                "    public String encode(PlatformClaimDto requestDto) throws BusinessException {\n" +
                "        // 码值转换\n" +
                "        codeChange(requestDto);\n" +
                "\n" +
                "        /* 拼接请求报文 */\n" +
                "        // 创建StringBuffer对象存储请求报文\n" +
                "        StringBuffer buf = new StringBuffer();\n" +
                "        // 添加报文编码格式\n" +
                "        pubTools.addXMLHeadGBK(buf);\n" +
                "        // 拼接报文\n" +
                "        addPacket(buf, requestDto);\n" +
                "        return buf.toString();\n" +
                "    }" +
                "" +
                "    private void addPacket(StringBuffer buf, PlatformClaimDto requestDto) throws BusinessException {\n" +
                "        buf.append(\"<PACKET type=\\\"REQUEST\\\" version=\\\"1.0\\\" >\");\n" +
                "        addHead(buf, requestDto);\n" +
                "        addBody(buf, requestDto);\n" +
                "        buf.append(\"</PACKET>\");\n" +
                "    }" +
                "" +
                "    private void addHead(StringBuffer buf, PlatformClaimDto requestDto) throws BusinessException {\n" +
                "        /* 赋值 */\n" +
                "        // 归属地\n" +
                "        String strComCode = requestDto.getComCode();\n" +
                "        // 类型\n" +
                "        String strRequestType = \"51\";\n" +
                "        // 用户名\n" +
                "        String strUser = pubTools.getPlatformUser(PLATFORMConstant.CONFIG_CI, strComCode);\n" +
                "        // 密码\n" +
                "        String strPassword = pubTools.getPlatformPassword(PLATFORMConstant.CONFIG_CI, strComCode);\n" +
                "\n" +
                "        // 组成报文\n" +
                "        buf.append(\"<HEAD>\");\n" +
                "        PubTools.addNode(buf, \"REQUEST_TYPE\", strRequestType);\n" +
                "        PubTools.addNode(buf, \"USER\", strUser);\n" +
                "        PubTools.addNode(buf, \"PASSWORD\", strPassword);\n" +
                "        buf.append(\"</HEAD>\");\n" +
                "    }" +
                "");
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        String listName = "";
        for (Map.Entry<Integer, Integer> entry : set) {
            System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());
            // 第一次循环生成取值代码
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                if (i == entry.getKey() - 1 && entry.getKey() == 1) {
                    String[] splitsPath = innerList.get(15).split("\\.");
                    System.out.println("    private void addBody(StringBuffer buf, PlatformClaimDto requestDto) {");
                    System.out.println("        buf.append(\"<BODY>\");");
                    for (int j = 0; j < splitsPath.length; j++) {
                        System.out.println("        add" + toUpperCaseFirstOne(lineToHump(splitsPath[j])) + "(buf, requestDto);");
                    }
                    System.out.println("        buf.append(\"</BODY>\");");
                    System.out.println("    }\n");
                }
                if (i == entry.getKey() - 1) {
                    // 拼接对象信息方法
                    System.out.println("    private void add" + toUpperCaseFirstOne(lineToHump(innerList.get(1))) + "(StringBuffer buf, PlatformClaimDto requestDto) throws BusinessException {");
                    System.out.println("        /* 获取数据信息 */");
                    String[] splits = innerList.get(2).split("\\.");

                    String superDtoName = toLowerCaseFirstOne(splits[0]);
                    String childDtoName = toLowerCaseFirstOne(splits[1]);
                    System.out.println("        " + splits[0] + " " + superDtoName + " = " + "requestDto" + ".get" + toUpperCaseFirstOne(superDtoName) + "();");
                    if (innerList.get(1).endsWith("LIST")) {
                        listName = toLowerCaseFirstOne(childDtoName.replace(superDtoName.replace("Dto", ""), "").replace("DataDto", ""));
                        System.out.println("        List<" + splits[1] + "> " + listName + "List = " + superDtoName + ".get" + toUpperCaseFirstOne(childDtoName).replace(toUpperCaseFirstOne(superDtoName.replace("Dto", "")), "").replace("DataDto", "") + "List();");
                    } else {
                        System.out.println("        " + splits[1] + " " + toLowerCaseFirstOne(childDtoName.replace(superDtoName.replace("Dto", ""), "").replace("Dto", "")) + " = " + superDtoName + ".get" + childDtoName.replace(toLowerCaseFirstOne(superDtoName.replace("Dto", "")), "").replace("Dto", "") + "();");
                    }
                }

                // 代码注释添加
                System.out.println("        // " + innerList.get(4));
                // 获取字段值
                System.out.println("        String " + toLowerCaseFirstOne(lineToHump(innerList.get(3))) + " = " + innerList.get(14) + ".get" + toUpperCaseFirstOne(lineToHump(innerList.get(3))) + "();");
            }

            System.out.println("");

            // 第二次循环生成报文拼接代码
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);
                String[] splits = innerList.get(2).split("\\.");
                if (i == entry.getKey() - 1) {
                    if (innerList.get(1).endsWith("LIST")) {
                        String serviceName = toLowerCaseFirstOne(splits[0]).replace("Dto", "");
                        System.out.println("        buf.append(\"<" + innerList.get(1) + ">\");\n" +
                                "        for (" + splits[1] + " " + toLowerCaseFirstOne(toLowerCaseFirstOne(splits[1]).replace(serviceName, "")) + " : " + listName + "List) {");
                    }
                    System.out.println("        buf.append(\"<" + (innerList.get(1).endsWith("LIST") ? innerList.get(1).replace("LIST", "DATA") : innerList.get(1)) + ">\");");
                    System.out.println("        // 报文拼接赋值");
                }

                // 生成拼接字段代码
                System.out.println("        PubTools.addNode(buf, \"" + innerList.get(3) + "\", " + toLowerCaseFirstOne(lineToHump(innerList.get(3))) + ");");

                if (i == (entry.getValue() - 1)) {
                    System.out.println("        buf.append(\"</" + (innerList.get(1).endsWith("LIST") ? innerList.get(1).replace("LIST", "DATA") : innerList.get(1)) + ">\");" +
                            "        }");
                    if (innerList.get(1).endsWith("LIST")) {
                        System.out.println("        buf.append(\"</" + innerList.get(1) + ">\");");
                        System.out.println("        }\n");
                    }
                }
            }
        }

        System.out.println("" +
                "    private void codeChange(PlatformClaimDto requestDto) throws BusinessException {\n" +
                "        System.out.println(\"码值转换\" + requestDto);\n" +
                "    }");
    }

    /**
     * 自动生成valid入参校验代码
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      请求起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void codeGenerationValid(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        for (Map.Entry<Integer, Integer> entry : set) {
            System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());

            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                if (i == entry.getKey() - 1 && entry.getKey() == 1) {
                    System.out.println("    @Override\n" +
                            "    public void valid(PlatformClaimDto requestDto) throws IllegalArgumentException {\n" +
                            "        // 校验对象");
                    String[] splitPath = innerList.get(15).split("\\.");
                    for (String s : splitPath) {
                        System.out.println("        "+lineToHump(s)+"Valid(requestDto);");
                    }
                    System.out.println("    }\n");
                }

                if (i == entry.getKey() - 1) {
                    // 拼接对象信息方法
                    System.out.println("    private void " + lineToHump(innerList.get(1)) + "Valid(PlatformClaimDto requestDto) throws IllegalArgumentException {");
                    String[] splits = innerList.get(2).split("\\.");

                    String superDtoName = toLowerCaseFirstOne(splits[0]);
                    String childDtoName = toLowerCaseFirstOne(splits[1]);
                    String oName = childDtoName.replace(superDtoName.replace("Dto", ""), "").replace("Dto", "");
                    String olName = childDtoName.replace(superDtoName.replace("Dto", ""), "").replace("DataDto", "");
                    System.out.println("        " + splits[0] + " " + superDtoName + " = " + "requestDto" + ".get" + toUpperCaseFirstOne(superDtoName) + "();");
                    if (innerList.get(1).endsWith("LIST")) {
                        System.out.println("        List<" + splits[1] + "> " + olName + "List = " + superDtoName + ".get" + toUpperCaseFirstOne(olName) + "List();");
                        System.out.println("        for (" + splits[1] + " " + innerList.get(14) + " : " + olName+ "List) {");
                    } else {
                        System.out.println("        " + splits[1] + " " + toLowerCaseFirstOne(oName) + " = " + superDtoName + ".get" + toUpperCaseFirstOne(oName) + "();");
                    }
                }

                if (innerList.get(7).endsWith("Y")) {
                    System.out.println("        if (StringUtils.isEmpty(" + innerList.get(14) + ".get" + toUpperCaseFirstOne(lineToHump(innerList.get(3))) + "())) {\n" +
                            "            throw new IllegalArgumentException(\"" + innerList.get(4) + "不能为空\");\n" +
                            "        }");
                }

                if (i == (entry.getValue() - 1)) {
                    System.out.println("        }");
                    if (innerList.get(1).endsWith("LIST")) {
                        System.out.println("    }");
                    }
                }
            }
        }
    }

    /**
     * 自动生成decode返回报文解析代码
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      返回数据起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void codeGenerationDecode(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        // 获取节点名称拼接返回对象名称
        String className = "";

        for (Map.Entry<Integer, Integer> entry : set) {
            System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());
            // 生成解析Body节点代码
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);
                if (i == entry.getKey() - 1 && entry.getKey() == 1) {
                    String[] splitsDto = (innerList.get(2).split("\\."));
                    className = splitsDto[0];
                    System.out.println("    private static final String SUCCESS_CODE = \"1\";\n" +
                            "    private static final String TS_CHARSET = \"%SinoSoft_GS%\";\n" +
                            "\n" +
                            "    @Override\n" +
                            "    public " + className + " decode(String responseXml) throws BusinessException {\n" +
                            "        // 定义返回对象\n" +
                            "        " + className + " responseDto = new " + className + "();\n" +
                            "\n" +
                            "        // 获取Document对象\n" +
                            "        Document document;\n" +
                            "        try {\n" +
                            "            document = ConversionDocument.createW3CDocument(responseXml.replaceAll(\"&\", TS_CHARSET));\n" +
                            "        } catch (Exception e) {\n" +
                            "            throw new BusinessException(\"返回报文获取Document对象异常\");\n" +
                            "        }\n" +
                            "\n" +
                            "        // 解析Head节点\n" +
                            "        processHead(XMLUtils.getChildNodeByPath(document, \"/PACKET/HEAD\"));\n" +
                            "        // 解析Body节点\n" +
                            "        processBody(responseDto, XMLUtils.getChildNodeByPath(document, \"/PACKET/BODY\"));\n" +
                            "        return responseDto;\n" +
                            "    }\n" +
                            "\n" +
                            "    private void processHead(Node node) {\n" +
                            "        // 获取返回码\n" +
                            "        String responseCode = XMLUtils.getChildNodeValue(node, \"RESPONSE_CODE\");\n" +
                            "        // 获取返回错误信息\n" +
                            "        String errorMessage = XMLUtils.getChildNodeValue(node, \"ERROR_MESSAGE\");\n" +
                            "\n" +
                            "        // 业务处理 返回错误时抛出自定义异常\n" +
                            "        if (!SUCCESS_CODE.equals(responseCode)) {\n" +
                            "            throw new BusinessException(\"平台返回错误：\" + errorMessage);\n" +
                            "        }\n" +
                            "    }\n");
                    String[] splitsPath = innerList.get(15).split("\\.");
                    System.out.println("    private void processBody(" + className + " responseDto, Node node) {");
                    for (int j = 0; j < splitsPath.length; j++) {
                        System.out.println("        process" + toUpperCaseFirstOne(lineToHump(splitsPath[j])) + "(responseDto, XMLUtils.getChildNodeByTagName(node, \"" + splitsPath[j] + "\"));");
                    }
                    System.out.println("    }\n");
                }
            }

            // 生成对象解析代码
            String classNameResponseHead = className.replace("ResponseDto", "");
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                // 拼接方法头
                if (i == entry.getKey() - 1) {
                    System.out.println("    private void process" + toUpperCaseFirstOne(lineToHump(innerList.get(1))) + "(" + className + " responseDto, Node node) throws BusinessException {");
                    if (innerList.get(1).endsWith("LIST")) {
                        if (innerList.get(1).equals("LOCKED_LIST")) {
                            System.out.println("        List<ClaimLockedDto> lockedList = new ArrayList<>();");
                        } else {
                            System.out.println("        List<" + classNameResponseHead + toUpperCaseFirstOne(lineToHump(innerList.get(1))).replace("List", "Data") + "Dto> " + toLowerCaseFirstOne(lineToHump(innerList.get(1))) + " = new ArrayList<>();");
                        }
                        System.out.println("        Node[] nodes = XMLUtils.getChildNodesByTagName(node, \"" + innerList.get(1).replace("LIST", "DATA") + "\");\n" +
                                "        for (Node childNode : nodes) {");
                    } else {
                        System.out.println("        " + classNameResponseHead + "Response" + toUpperCaseFirstOne(lineToHump(innerList.get(1))) + "Dto " + toLowerCaseFirstOne(lineToHump(innerList.get(1))) + " = new " + classNameResponseHead + toUpperCaseFirstOne(lineToHump(innerList.get(1))) + "Dto();");
                    }
                }

                if (innerList.get(1).endsWith("LIST")) {
                    // 拼接方法内容
                    System.out.println("            // " + innerList.get(4) + "\n" +
                            "            String " + lineToHump(innerList.get(3)) + " = XMLUtils.getChildNodeValue(childNode, \"" + innerList.get(3) + "\");");
                } else {
                    // 拼接方法内容
                    System.out.println("            // " + innerList.get(4) + "\n" +
                            "            String " + lineToHump(innerList.get(3)) + " = XMLUtils.getChildNodeValue(node, \"" + innerList.get(3) + "\");");
                }
            }

            // 生成代码赋值对象
            String dtoName = "";
            String superName = "";
            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);
                if (i == (entry.getKey() - 1)) {
                    String[] splitsDto = (innerList.get(2).split("\\."));
                    superName = toLowerCaseFirstOne(splitsDto[0].replace("ResponseDto", ""));
                    // 生成赋值部分代码
                    System.out.println("            // 对象赋值\n");
                    if (innerList.get(1).endsWith("LIST")) {
                        if (innerList.get(1).equals("LOCKED_LIST")) {
                            System.out.println("            ClaimLockedDto claimLockedDto = new ClaimLockedDto();");
                            dtoName = "claimLockedDto";
                        } else {
                            String cName = splitsDto[0].replace("ResponseDto", "") + toUpperCaseFirstOne(lineToHump(innerList.get(1).replace("LIST", "DATA")));
                            System.out.println("            " + cName + " " + toLowerCaseFirstOne(cName) + " = new " + cName + "();");
                            dtoName = toLowerCaseFirstOne(cName);
                        }
                    } else {
                        String cName = splitsDto[0].replace("ResponseDto", "") + toUpperCaseFirstOne(lineToHump(innerList.get(1)));
                        dtoName = toLowerCaseFirstOne(cName);
                    }
                }
                System.out.println("            " + toLowerCaseFirstOne(dtoName.replace(superName, "")) + ".set" + toUpperCaseFirstOne(lineToHump(innerList.get(3))) + "(" + lineToHump(innerList.get(3)) + ");");
                // 拼接方法尾
                if (i == (entry.getValue() - 1)) {
                    if (toUpperCaseFirstOne(innerList.get(1)).endsWith("LIST")) {
                        System.out.println("        }");
                    }
                    System.out.println("        /* 赋值到返回对象 */\n" +
                            "        responseDto.set" + toUpperCaseFirstOne(lineToHump(innerList.get(1))) + "(" + lineToHump(innerList.get(1)) + ");");
                    System.out.println("    }");
                }
            }
        }
    }

    /**
     * 自动生成dto代码
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void codeGenerationDto(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        for (Map.Entry<Integer, Integer> entry : set) {
            System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());

            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                System.out.println("/**\n" +
                        "     * " + innerList.get(4) + "\n" +
                        "     */\n" +
                        "    private String " + lineToHump(innerList.get(3)) + ";");
            }

        }
    }

    /**
     * 自动生成set方法
     *
     * @param mapFromExcel 存放待读取行数
     * @param totalPages   sheet页
     * @param topRows      起始读取行
     * @param totalCells   读取列数
     * @param filePath     待读取文件全路径名
     * @author 李坤尧
     */
    public static void autoGenerateSetMethod(LinkedHashMap<Integer, Integer> mapFromExcel, int totalPages, int topRows, int totalCells, String filePath) {
        List<ArrayList<String>> dataList = new ZhongTaiExcel(totalPages, topRows, totalCells).read(filePath);

        Set<Map.Entry<Integer, Integer>> set = mapFromExcel.entrySet();

        for (Map.Entry<Integer, Integer> entry : set) {
            System.out.println("// 截取行数:" + entry.getKey() + "--->" + entry.getValue());

            for (int i = entry.getKey() - 1; i < entry.getValue(); i++) {
                // 获取单行数据
                ArrayList<String> innerList = dataList.get(i);

                String className = lineToHump(innerList.get(1));
                String setMethodName = lineToHump("SET_" + innerList.get(2));

                String comments = innerList.get(1) + "   参数属性:" + innerList.get(2) + "   参数名:" + innerList.get(3) + "   是否必录:" + innerList.get(6);
                System.out.println("// " + comments);

                System.out.print(className + "." + setMethodName + "(");
                System.out.print("MapUtils.methodGetValue(map, \"" + toLowerCaseFirstOne(innerList.get(11)) + "\", \"" + toLowerCaseFirstOne(innerList.get(12)) + "\")");
                System.out.println(");");
            }

        }
    }

    /**
     * 下划线转驼峰
     *
     * @param str 下划线字符串
     * @return 驼峰字符串
     * @author 李坤尧
     */
    public static String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 首字母转小写
     *
     * @param s 待转字符串
     * @return 首字母转小写
     * @author 李坤尧
     */
    public static String toLowerCaseFirstOne(String s) {
        if (s == null || "".equals(s)) {
            return "";
        }
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }

    /**
     * 首字母转大写
     *
     * @param s 待转字符串
     * @return 首字母转大写
     * @author 李坤尧
     */
    public static String toUpperCaseFirstOne(String s) {
        if (s == null || "".equals(s)) {
            return "";
        }
        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toUpperCase(s.charAt(0)) + s.substring(1);
        }
    }

    public static String sex(String s) {
        if ("男".equals(s)) {
            return "MALE";
        } else if ("女".equals(s)) {
            return "FEML";
        } else {
            return s;
        }

    }

    /**
     * 写文件
     *
     * @param newFile
     * @param str
     * @throws Exception
     */
    public static void write(String newFile, String str) {
        BufferedWriter bw;
        try {
            bw = new BufferedWriter(new FileWriter(new File(newFile)));
            bw.write(str);
            bw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * <ul>
     * <li>Description:[根据文件名读取excel文件]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    public List<ArrayList<String>> read(String fileName) {
        List<ArrayList<String>> dataLst = new ArrayList<>();

        /** 检查文件名是否为空或者是否是Excel格式的文件 */
        if (fileName == null || !fileName.matches("^.+\\.(?i)((xls)|(xlsx))$")) {
            return dataLst;
        }

        boolean isExcel2003 = true;
        /** 对文件的合法性进行验证 */
        if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
            isExcel2003 = false;
        }

        /** 检查文件是否存在 */
        File file = new File(fileName);
        if (file == null || !file.exists()) {
            return dataLst;
        }

        try {
            /** 调用本类提供的根据流读取的方法 */
            dataLst = read(new FileInputStream(file), isExcel2003);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        /** 返回最后读取的结果 */
        return dataLst;
    }

    /**
     * <ul>
     * <li>Description:[根据流读取Excel文件]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @param inputStream
     * @param isExcel2003
     * @return
     */
    public List<ArrayList<String>> read(InputStream inputStream, boolean isExcel2003) {
        List<ArrayList<String>> dataLst = null;
        try {
            /** 根据版本选择创建Workbook的方式 */
            Workbook wb = isExcel2003 ? new HSSFWorkbook(inputStream) : new XSSFWorkbook(inputStream);
            dataLst = read(wb);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataLst;
    }

    /**
     * <ul>
     * <li>Description:[得到总行数]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @return
     */
    public int getTotalRows() {
        return totalRows;
    }

    /**
     * <ul>
     * <li>Description:[得到总列数]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @return
     */
    public int getTotalCells() {
        return totalCells;
    }

    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    /**
     * <ul>
     * <li>Description:[读取数据]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @param wb
     * @return
     */
    private List<ArrayList<String>> read(Workbook wb) {
        List<ArrayList<String>> dataLst = new ArrayList<>();

        /** 得到第一个shell */
        Sheet sheet = wb.getSheetAt(this.getTotalPages());
        this.totalRows = sheet.getPhysicalNumberOfRows();
        // if (this.totalRows >= 1 && sheet.getRow(0) != null)
        // {
        // this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        // }

        /** 循环Excel的行 */
        for (int r = this.topRows; r < this.totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                continue;
            }

            ArrayList<String> rowLst = new ArrayList<>();
            /** 循环Excel的列 */
            for (short c = 0; c < this.getTotalCells(); c++) {
                Cell cell = row.getCell(c);
                String cellValue = "";
                if (cell == null) {
                    rowLst.add(cellValue);
                    continue;
                }

                /** 处理数字型的,自动去零 */
                if (Cell.CELL_TYPE_NUMERIC == cell.getCellType()) {
                    /** 在excel里,日期也是数字,在此要进行判断 */
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        Date ccellValue = cell.getDateCellValue();
                        cellValue = CalendarUtil.getDate(ccellValue, "yyyy-MM-dd");
                    } else {
                        cellValue = getRightStr(cell.getNumericCellValue() + "");
                    }
                }
                /** 处理字符串型 */
                else if (Cell.CELL_TYPE_STRING == cell.getCellType()) {
                    cellValue = cell.getStringCellValue();
                }
                /** 处理布尔型 */
                else if (Cell.CELL_TYPE_BOOLEAN == cell.getCellType()) {
                    cellValue = cell.getBooleanCellValue() + "";
                }
                /** 其它的,非以上几种数据类型 */
                else {
                    cellValue = cell.toString() + "";
                }

                rowLst.add(cellValue);
            }
            dataLst.add(rowLst);
        }
        return dataLst;
    }

    /**
     * <ul>
     * <li>Description:[正确地处理整数后自动加零的情况]</li>
     * <li>Created by [Huyvanpull] [Jan 20, 2010]</li>
     * <li>Midified by [modifier] [modified time]</li>
     * <ul>
     *
     * @param sNum
     * @return
     */
    private String getRightStr(String sNum) {
        DecimalFormat decimalFormat = new DecimalFormat("#.000000");
        String resultStr = decimalFormat.format(new Double(sNum));
        if (resultStr.matches("^[-+]?\\d+\\.[0]+$")) {
            resultStr = resultStr.substring(0, resultStr.indexOf("."));
        }
        return resultStr;
    }

    public int getTopRows() {
        return topRows;
    }

    public void setTopRows(int topRows) {
        this.topRows = topRows;
    }

}
